// 面向对象轮播图构造函数
// 参数1 父级标签对象
// 参数2 数据数组

class SetBanner {
    constructor(element, array) {
        this.ele = element;
        this.arr = array;
        // 定义属性 存储数据
        this.oUl = this.ele.querySelector('ul');
        this.oOl = this.ele.querySelector('ol');


        // 定义变量 准备存储数据 
        this.length = this.arr.length;
        this.index = 1;
        this.bool = true;
        this.liWidth;
        this.ollis;
        this.ullis;
        this.time;

    }

    // 定义一个函数方法,调用执行所有需要执行的函数程序
    // 这个函数称为入口函数 统一命名为 init
    init(){
        this.setPage();
        this.autoLoop();
        this.setInOut();
        this.setClick();
        this.hide();
    }

    // 函数方法1 动态生成页面
    setPage() {
        // 动态渲染生成页面
        //  定义字符串 
        let ulStr = '';
        let olStr = '';

        //  循环遍历数组
        this.arr.forEach((item, key) => {
            // 字符串根据数组拼接内容
            ulStr += `<li><img src="../message/${item.path}"></li>`;

            // 第一个ol>li 有 class,active
            olStr += key === 0 ? `<li class="active" name="olli" num="${key}"></li>` : `<li name="olli"  num="${key}"></li>`;
        })

        // 写入 ul ol 标签对象
        this.oUl.innerHTML = ulStr;
        this.oOl.innerHTML = olStr;

        // 获取所有的 ul>li
        this.ullis = this.oUl.querySelectorAll('li');

        // 获取所有的 ol>li 
        this.ollis = this.oOl.querySelectorAll('li');

        // 获取 原始 ul>li 中的 第一个 和 最后一个
        const first = this.ullis[0];
        const last = this.ullis[this.length - 1];

        // 克隆 原始第一个 和 克隆 原始最后一个
        const cloneFirst = first.cloneNode(true);
        const cloneLast = last.cloneNode(true);

        // 克隆的标签对象的写入 语法

        // 在 oUl 标签的 最后 写入 新的 标签对象
        this.oUl.appendChild(cloneFirst);
        // 在 oUl 标签 中 第一个标签 之前 写入 克隆的最后一个标签
        this.oUl.insertBefore(cloneLast, first);

        // 获取li标签宽度
        this.liWidth = parseInt(myGetStyle(first, 'width'));

        // 重新设定 ul标签的宽度
        // 当前li的个数 * 一个li的宽度
        // 当前li的个数 原始li个数+1   原始数组单元个数+2
        this.oUl.style.width = (this.length + 2) * this.liWidth + 'px';

        // 给 ul 定位 向左 定位 1个li的宽度
        this.oUl.style.left = -this.liWidth * this.index + 'px';
    }

    // 函数方法2 自动轮播
    autoLoop() {
        // 定义定时器 执行程序
        this.time = setInterval(() => {
            //  变量index 累加
            this.index++;

            // index累加之后 执行样式切函数
            this.setFocusStyle();

            //  根据 新的index 设定 ul标签的定位
            //  left 定位 是 -li宽度*index的数值(显示li的索引下标) + 'xp'
            //  通过move()运动函数完成

            // 方法1: 修改 loopEnd 函数的this指向 通过 bind 修改this指向为 当前this指向也就是 实例化对象
            move(this.oUl, { left: -this.index * this.liWidth }, this.loopEnd.bind(this));

            // 方法2: 将绑定函数名称的语法形式 修改为 绑定一个箭头函数
            // 箭头函数的this指向是父级程序 也就是 实例化对象
            //
            // move(this.oUl, { left: -this.index * this.liWidth }, ()=>{
            //     // 此处 this指向是 实例化对象
            //     // 也就是 当前 调用 loopEnd 函数程序 this 指向是 实例化对象
            //     this.loopEnd();
            // });

        }, 3000);
    }

    // 函数方法3 轮播运动结束的回调函数
    loopEnd() {
        if (this.index === this.length + 2 - 1) {
            // index 赋值第二个li 索引下标 也就是 赋值1
            this.index = 1;
            // 根据新的index 重新定位ul
            this.oUl.style.left = -this.liWidth * this.index + 'px';

            // 如果 index 是 0 给 index赋值 当前ul中倒数第二个li的索引下标
        } else if (this.index === 0) {
            // index 赋值倒数第二个li 索引下标 也就是 赋值 length
            this.index = this.length;
            // 根据新的index 重新定位ul
            this.oUl.style.left = -this.liWidth * this.index + 'px';
        }

        // 给 bool 赋值原始值 true
        this.bool = true;
    }

    // 函数方法4 焦点样式设定函数
    setFocusStyle() {
        // 1, 循环遍历所有的ol>li 清除 class,active
        // item就是 ol中的li
        this.ollis.forEach(item => {
            // 给 item 也就是 ol 中的 li 清除 class,active
            item.classList.remove('active');
        })

        // 2, 给 索引下标 是 index-1 的 ol>li 添加 class,active

        // 如果 显示的是 当前ul中最后一个li 实际需要给 当前ol中第一个焦点添加样式
        if (this.index === this.length + 2 - 1) {
            this.ollis[0].classList.add('active');

            // 如果 显示的是 当前ul中第一个li 实际需要给 当前ol中最后有一个焦点添加样式
        } else if (this.index === 0) {
            this.ollis[this.length - 1].classList.add('active');
        } else {
            this.ollis[this.index - 1].classList.add('active');
        }
    }

    // 函数方法5 鼠标的移入移出
    setInOut() {
        // 父级标签添加移入事件
        this.ele.addEventListener('mouseenter', () => {
            // 清除定时器
            clearInterval(this.time);
        })

        // 父级标签添加移出事件
        this.ele.addEventListener('mouseleave', () => {
            // 再次调用自动轮播函数
            this.autoLoop();
        })
    }


    // 函数6 点击事件
    setClick() {
        // 给父级div标签添加点击事件 执行事件委托
        this.ele.addEventListener('click', e => {
            // 判断点击的目标
            if (e.target.getAttribute('name') === 'left') {
                // 防止点击过快
                if (this.bool) {
                    this.bool = false;
                } else {
                    return;
                }

                // 点击的是 左按钮 显示左侧图片 index--
                this.index--;

                // 调用函数 完成 焦点样式设定
                this.setFocusStyle();

                // 根据新的index 动态设定 ul定位 
                // 也就是 调用 move() 运动函数 根据新的index完成ul定位
                move(this.oUl, { left: -this.index * this.liWidth }, this.loopEnd.bind(this));

            } else if (e.target.getAttribute('name') === 'right') {
                // 防止点击过快
                if (this.bool) {
                    this.bool = false;
                } else {
                    return;
                }

                // 点击的是 右按钮 显示右侧图片 index++
                this.index++;

                // 调用函数 完成 焦点样式设定
                this.setFocusStyle();

                // 根据新的index 动态设定 ul定位 
                // 也就是 调用 move() 运动函数 根据新的index完成ul定位
                move(this.oUl, { left: -this.index * this.liWidth }, this.loopEnd.bind(this));

            } else if (e.target.getAttribute('name') === 'olli') {
                // 防止点击过快
                if (this.bool) {
                    this.bool = false;
                } else {
                    return;
                }


                // 点击的标签 name是 olli 也就是 点击的是 焦点li标签
                // 获取点击标签 num属性的属性值 +1 赋值给 index变量
                this.index = e.target.getAttribute('num') - 0 + 1;

                // 调用函数 完成 焦点样式设定
                this.setFocusStyle();

                // 根据新的index 动态设定 ul定位 
                // 也就是 调用 move() 运动函数 根据新的index完成ul定位
                move(this.oUl, { left: -this.index * this.liWidth }, this.loopEnd.bind(this));

            }
        })
    }

    // // 函数7 浏览器最小化事件
    hide() {
        // visibilitychange 显示状态监听事件
        // 显示状态改变时 会触发程序
        // document.visibilityState 显示状态码  
        // hidden 隐藏   visible 显示
        document.addEventListener('visibilitychange', () => {
            if (document.visibilityState === 'hidden') {
                // 隐藏 清除 定时器
                clearInterval(this.time)
            } else if (document.visibilityState === 'visible') {
                // 显示 再次 调用自动轮播函数
                this.autoLoop();
            }
        })
    }
}